'''
清空操作：原图 AND 掩码 (保留高位)
提取操作：秘密图 AND 掩码 (隔离特定位)
嵌入操作：载体图 OR 秘密数据 (写入低位)

B/G通道各存储3位信息（最大可存储值7）
R通道存储2位信息（最大可存储值3）
总嵌入容量：3+3+2=8位/像素（完整灰度信息）
'''

import cv2
import numpy as np
def display_image(image, window_name='end', window_size=(500, 500)):
    try:
        cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
        cv2.resizeWindow(window_name, *window_size)
        cv2.imshow(window_name, image)
        return 1
        # 等待用户按键(默认1ms延迟，0表示无限等待)
        # key = cv2.waitKey(0) & 0xFF
        # cv2.destroyAllWindows()
        # return key
    except Exception as e:
        print(f"图像显示错误: {str(e)}")
        return -1


# 读取彩色图像map2.png
img1 = cv2.imread(r"4/map2.png")
img1 = cv2.resize(img1, None, fx=0.5, fy=0.5)
x, y, z = img1.shape

# 读取灰度图像map1.png并转换为8位灰度图
img2 = cv2.imread(r"4/map1.png", 0)
img2 = cv2.resize(img2, (y, x))

# 提取三个通道信息
B = img1[:, :, 0]
G = img1[:, :, 1]
R = img1[:, :, 2]

'''
位平面处理原理 (Bit-plane processing):
灰度图分解到3个通道，彩色通道的低位用于隐藏数据 
8位灰度图分解方案: 3位 | 3位 | 2位 (前3位给B通道，中间3位给G，最后2位给R)
对应掩码:
  B通道: 11100000 -> 右移5位 (除以32)
  G通道: 00011100 -> 右移2位 (除以4)
  R通道: 00000011 -> 不需移位 
'''
# 将三个通道图像的低平面位置0
clean_mask1 = np.ones(B.shape, dtype=np.uint8) * 248  # 11111000
clean_mask2 = np.ones(B.shape, dtype=np.uint8) * 252  # 11111100
temp_b = cv2.bitwise_and(B, clean_mask1)# B通道保留高5位
temp_G = cv2.bitwise_and(G, clean_mask1)# B通道保留高5位
temp_R = cv2.bitwise_and(R, clean_mask2) # R通道保留高6位

# 构建提取矩阵，分别提取被隐藏图像：012，345，67个位平面信息
extract_mask1 = np.ones(B.shape, dtype=np.uint8) * 7    # 00000111 (提取0-2位)3
extract_mask2 = np.ones(B.shape, dtype=np.uint8) * 56   # 00111000 (提取3-5位)3
extract_mask3 = np.ones(B.shape, dtype=np.uint8) * 192  # 11000000 (提取6-7位)2

# 提取隐藏层信息
hidden1 = cv2.bitwise_and(img2, extract_mask1)# 获取最低3位 (0-2)
hidden2 = cv2.bitwise_and(img2, extract_mask2)
hidden3 = cv2.bitwise_and(img2, extract_mask3)


print('显示三个提取出来的图像')
display_image(image=hidden1, window_name='hidden1',window_size=(400, 400))
display_image(image=hidden2,window_name='hidden2',window_size=(400, 400))
display_image(image=hidden3,window_name='hidden3',window_size=(400, 400))

# 显示三个提取出来的图像
# cv2.imshow("hidden1", hidden1)
# cv2.imshow("hidden2", hidden2)
# cv2.imshow("hidden3", hidden3)
cv2.waitKey()
cv2.destroyAllWindows()

# 将位平面层次进行还原
hidden2 = hidden2 // 8  # 将hidden2中第3，4，5位平面的数据移动到0,1,2位平面  # 右移3位 (原3-5位 -> 0-2位)
hidden3 = hidden3 // 64  # 将hidden3中第6，7位平面的数据移动到0,1位平面 # 右移6位 (原6-7位 -> 0-1位)

print('显示还原后的三个图像')
display_image(image=hidden1,window_name='hidden1',window_size=(400, 400))
display_image(image=hidden2,window_name='hidden2',window_size=(400, 400))
display_image(image=hidden3,window_name='hidden3',window_size=(400, 400))
# # 显示还原后的三个图像
# cv2.imshow("hidden1", hidden1)
# cv2.imshow("hidden2", hidden2)
# cv2.imshow("hidden3", hidden3)
cv2.waitKey()
cv2.destroyAllWindows()

# 隐藏：将hidden1,hidden2,hidden3分别隐藏到img1中RGB三个通道中
# 这里需要注意：temp_b, temp_G是清空了3个位平面，temp_R是清空了2个位平面
# hidden1，hidden2是取了3个位平面，hidden3是两个位平面
# 清空的位平面数要和要隐藏图像的位平面数对应

temp_b = cv2.bitwise_or(temp_b, hidden1) # B通道嵌入低3位
temp_G = cv2.bitwise_or(temp_G, hidden2) # G通道嵌入低3位
temp_R = cv2.bitwise_or(temp_R, hidden3)# R通道嵌入低2位
print('分别显示三个通道的图像')
display_image(image=temp_b,window_name='b',window_size=(400, 400))
display_image(image=temp_G,window_name='g',window_size=(400, 400))
display_image(image=temp_R,window_name='r',window_size=(400, 400))
# 分别显示三个通道的图像
# cv2.imshow("temp_b", temp_b)
# cv2.imshow("temp_G", temp_G)
# cv2.imshow("temp_R", temp_R)
cv2.waitKey()
cv2.destroyAllWindows()

# 合并三个通道
hidden_result = cv2.merge([temp_b, temp_G, temp_R])

# 显示合并图像
print('显示合并图像')
display_image(image=img1,window_name='Original',window_size=(400, 400))
display_image(image=hidden_result,window_name='hidden_result',window_size=(400, 400))
# cv2.imshow("Original", img1)
# cv2.imshow("hidden_result", hidden_result)
cv2.waitKey()
cv2.destroyAllWindows()

# 保存结果
cv2.imwrite(r"hidden_result.bmp", hidden_result)# 无损格式
cv2.imwrite(r"hidden_result.jpeg", hidden_result)
